package com.frank.threadPool;

import java.util.concurrent.*;

/**
 * @author 小石潭记
 * @date 2021/4/3 10:10
 *
 * @Description: return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
 *                                       60L, TimeUnit.SECONDS,
 *                                       new SynchronousQueue<Runnable>());
 */
public class Test3 {

    public static void main(String[] args) throws InterruptedException {
        long start = System.currentTimeMillis();
        // 同步的队列
        ExecutorService executorService1 = Executors.newCachedThreadPool(); //1054
        ExecutorService executorService2 = Executors.newFixedThreadPool(10); //10017
        ExecutorService executorService3 = Executors.newSingleThreadExecutor(); // 100056
        // 自定义线程池
        // 第31个就开始异常了
        // 核心员工10个 最大值20个 非核心员工也是20-10=10个，核心员工1-10，
        // 11-20存入队列中，21-30存入非核心员工，31-40时，无法交付，则抛出异常，被拒绝
        // 提交优先级 核心员工 > 队列 > 非核心员工
        // 执行优先级 核心员工 > 非核心员工 > 队列
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20,
                // 这里是设置非核心员工的“合同年限”（给线程续命的~~）
                0L,
                TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<>(10));
        for (int i = 1; i <= 100; i++) {
            // execute() 里面三个if 则是提交优先级的判断  addWorker都会有这个方法
            // addWorker(Runnable firstTask, boolean core)
            //  private final class Worker
            //        extends AbstractQueuedSynchronizer
            //        implements Runnable
            // w = new Worker(firstTask); 这里的worker是实现了runnable接口
            // 查看run方法  Worker分核心和非核心 task任务不分
            // while (task != null || (task = getTask()) != null)  执行优先级
            // task不为空 则直接执行，否则才会去队列里面取
            threadPoolExecutor.execute(new MyTask(i));
        }
        // 阻止新来的任务提交，对已经提交了的任务不会产生任何影响。当已经提交的任务执行完后，
        // 它会将那些闲置的线程（idleWorks）进行中断，这个过程是异步的。
       /* executorService1.shutdown();
        // awaitTermination会一直等待，直到线程池状态为TERMINATED或者，
        // 等待的时间到达了指定的时间。
        executorService1.awaitTermination(1, TimeUnit.DAYS);
        System.out.println("时间：" + (System.currentTimeMillis() - start));*/
    }
}

